#include "CurlBase.h"

gchar *APPLICATION_JSON = "Content-Type: application/json";
gchar *FORM_POST = "Content-Type: application/x-www-form-urlencoded";

CURL *CurlInit(){
    CURL *curl;
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if(curl) {
        return curl;
    }
    return NULL;
}

struct curl_slist *Headers(char *Header, ...){
    struct curl_slist *headers = NULL;
    va_list argslist;
    va_start(argslist, Header);
    headers = curl_slist_append(headers,Header);

    char *para;
    while((para = va_arg(argslist,char* ))!=NULL){
        headers = curl_slist_append(headers, para);
    }
    va_end(argslist);
    return headers;
}

gchar *HttpJsonGet(char *url){
    CURL *curl = CurlInit();
    CURLcode res;
    if(curl){
        struct string s;
        init_string(&s);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK){
            fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
            return Error("Res Error");
        }
        curl_easy_cleanup(curl);
        return (gchar *)s.ptr;
    }
    return Error("Curl Error");
}

gchar *HttpValuePost(char *url, GString *parameter){
    CURL *curl = CurlInit();
    CURLcode res;
    if(curl){
        struct string s;
        init_string(&s);
        struct curl_slist *header = Headers(FORM_POST,NULL);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_string_free(parameter,FALSE));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
        res = curl_easy_perform(curl);

        if(res != CURLE_OK){
            fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
            return Error("Res Error");
        }
        curl_easy_cleanup(curl);
        return (gchar *)s.ptr;
    }
    return Error("Curl Error");
}

gchar *HttpJsonPost(char *url, GString *json_value){
    CURL *curl = CurlInit();
    CURLcode res;
    if(curl){
        struct string s;
        init_string(&s);
        struct curl_slist *header = Headers(APPLICATION_JSON,NULL);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_string_free(json_value,FALSE));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
        res = curl_easy_perform(curl);

        if(res != CURLE_OK){
            fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
            return Error("Res Error");
        }
        curl_easy_cleanup(curl);
        return (gchar *)s.ptr;
    }
    return Error("Curl Error");
}

void CurlFileFormTableIterator(gpointer key, gpointer value, gpointer *curl_data){
    GData **dataset = (GData **)curl_data;
    struct curl_httppost *formpost = (struct curl_httppost *)g_dataset_get_data(dataset,"formpost");
    struct curl_httppost *lastptr = (struct curl_httppost *)g_dataset_get_data(dataset,"lastptr");

    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, (gchar *)key,
                 CURLFORM_COPYCONTENTS, (gchar *)value,
                 CURLFORM_END);

    g_dataset_set_data(dataset,"formpost",(gpointer)formpost);
    g_dataset_set_data(dataset,"lastptr",(gpointer)lastptr);
}

gchar *HttpFilePost(char *url, char *file_form_mos, char *file_name, GHashTable *table){
    CURL *curl = CurlInit();
    CURLcode res;

    struct curl_httppost *formpost = NULL;
    struct curl_httppost *lastptr = NULL;
    struct curl_slist *headerlist = NULL;
    static const char buf[] = "Expect:";
    curl_global_init(CURL_GLOBAL_ALL);

    GData *dataset;
    g_datalist_init(&dataset);

    g_hash_table_foreach(table,(GHFunc) CurlFileFormTableIterator,(gpointer)&dataset);
    formpost = (struct curl_httppost *)g_dataset_get_data(&dataset,"formpost");
    lastptr = (struct curl_httppost *)g_dataset_get_data(&dataset,"lastptr");

    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, file_form_mos,
                 CURLFORM_FILE, file_name,
                 CURLFORM_END);
    curl = curl_easy_init();
    headerlist = curl_slist_append(headerlist, buf);
    if(curl){
        struct string s;
        init_string(&s);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK){
            fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
            return Error("Res Error");
        }

        /* always cleanup */
        curl_easy_cleanup(curl);

        /* then cleanup the formpost chain */
        curl_formfree(formpost);
        /* free slist */
        curl_slist_free_all(headerlist);
        return (gchar *)s.ptr;
    }
    return Error("Curl Error");
}


gboolean HttpGetResourceByJson(char *ResourceUrl, GString *json_buffer, gchar *OutFileName){
    CURL *curl = CurlInit();
    CURLcode res;
    if(curl){
        FILE *fp;
        fp = fopen(OutFileName,"wb");

        struct curl_slist *header = Headers(APPLICATION_JSON,NULL);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);

        curl_easy_setopt(curl, CURLOPT_URL, ResourceUrl);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, g_string_free(json_buffer,FALSE));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);

        if(res!= CURLE_OK){
            g_print("%s\n",Error("Res Error"));
            return FALSE;
        }
        curl_easy_cleanup(curl);
        fclose(fp);
        return TRUE;
    }
    return FALSE;
}

gchar *SetPostBody(char *firstkey, ...){
    /***************************************/
    GString *RESULT = g_string_new(NULL);
    va_list argslist;
    va_start(argslist, firstkey);
    int mos=0;
    char *para = firstkey;
    g_string_append_printf(RESULT,"%s=",para);
    while((para = va_arg(argslist,char *))!= NULL){
        if(mos == 1){
            g_string_append_printf(RESULT,"%s=",para);
            mos = 0;
        }else{
            g_string_append_printf(RESULT,"%s&",para);
        }
        mos++;
    }
    va_end(argslist);
    gchar *resultvalue = g_string_free(RESULT,FALSE);
    resultvalue[strlen(resultvalue)-1] = '\0';
    /***************************************/
    return resultvalue;
}
